home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / tool / dolmorph / src / points.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-19  |  36.7 KB  |  1,347 lines

  1. /*===========================================
  2.           DolphMorph(ドルフモーフ)
  3.  
  4.       モーフィング&変形アニメ作成ソフト
  5.  
  6.   モーフィングアルゴリズム: EAST 1994
  7.   インターフェース作成:     松内 良介 1994
  8. ===========================================*/
  9. #define    MODULE_POINTS
  10. /*
  11.     モジュール points.c
  12.  
  13.     操作点ウィンドウに関する実現部
  14.  
  15.             int        init_points(void)
  16.             void    end_points(void)
  17.  
  18.         ●操作点構造体の生成/消滅
  19.     static    CPOINT    *cpoint_new(int type, int x, int y)
  20.     static    void    cpoint_delete(CPOINT *pcp)
  21.  
  22.         ●表示画像、操作点に関する座標取得/チェック
  23.             void    points_whereis(int scrx, int scry, int *side, int *n)
  24.     static    void    getImageFrame(int side, FRAME *fr)
  25.     static    int        checkOnImage(int scrx, int scry, int *imgx, int *imgy)
  26.     static    void    getPointXY(int side, int num, int *scrx, int *scry)
  27.     static    int        checkOnPoint(int side, int imagex, int imagey,
  28.                                  int *pDx, int *pDy)
  29.  
  30.         ●操作点、A/B画像の表示
  31.     static    void    setClipImage(int side)
  32.     static    void    _drawPoint(int side, int n, int mode)
  33.     static    void    _drawRubber(int side,int n, int flag, int mode)
  34.     static    void    dispPoints(void)
  35.     static    void    dispImages(void)
  36.  
  37.         ●指定した操作点の作成/移動/消去
  38.     static    void    makeControlPoint(int type, int imgx, int imgy)
  39.     static    void    moveControlPoint(int side,int num,int dx,int dy)
  40.     static    void    deleteControlPoint(int side,int num)
  41.  
  42.         ●操作点の作成のイベントループ
  43.     static    void    points_makeNewPoints(EVENT *pev)
  44.  
  45.         ●操作点ウィンドウへの画像の登録
  46.             void    points_storeImage(int side, IMAGE *im)
  47.  
  48.         ●モーフィング処理用の通信関数
  49.     static    void    dispXY2imageXY(int dispx,int dispy,int dispwid,int dispht,
  50.                                int imagewid, int imageht, int *ix,int *iy)
  51.             int        points_makeMorphPoints(LIST *plPOINT, LIST *plLINE)
  52.             int        points_checkMorphImages(void)
  53.             void    points_getImageSize(int *pwid,int *pht)
  54.             int        morphGetFromPixel(fxp x, fxp y, int *r,int *g,int *b)
  55.             int        morphGetToPixel(fxp x, fxp y, int *r,int *g,int *b)
  56.  
  57.         ●デスクトップメニューから呼び出される関数
  58.             int        points_checkLoadPoints(void)
  59.             void    points_loadPoints(void)
  60.             int        points_checkSavePoints(void)
  61.             void    points_savePoints(void)
  62.             int        points_checkClearPoints(void)
  63.             void    points_clearPoints(void)
  64.             void    points_loadImage(int side)
  65.  
  66.         ●操作点設定ウィンドウ上の部品から呼び出される関数
  67.             int        PointsWinFunc(kobj, messId, argc, pev, trigger)
  68.             int        PointsTypeTIconFunc(kobj, messId, argc, pev, trigger)
  69.             int        PointsCommandTIconFunc(kobj, messId, argc, pev, trigger)
  70.             int        PointsEditDBtnFunc(kobj, messId, argc, pev, trigger)
  71. */
  72.  
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <string.h>
  76. #include <winb.h>
  77. #include <te.h>
  78. #include <fntb.h>
  79. #include <gui.h>
  80. #include <egb.h>
  81. #include <wgb.h>
  82. #include <msdos.cf>
  83. #include <file_dlg.h>
  84.  
  85. #include <ryosuke.h>
  86. #include <usrlib.h>
  87.  
  88. #include "morph.h"
  89. #include "desktop.h"
  90. #include "points.h"
  91. #include "wgbmac.h"
  92. #include "guisub.h"
  93. #include "image.h"
  94. #include "fifo.h"
  95. #include "domorph.h"
  96. #include "imstore.h"
  97. #include "morphgo.h"
  98. #include "alert.h"
  99. #include "sub.h"
  100.  
  101. /*--------------------------------------------------------*/
  102. /*                        部品ID                        */
  103. /*--------------------------------------------------------*/
  104.  
  105.     int    idPointsWin = -1 ;
  106.     int    idPointsTitleDBtn = -1 ;
  107.     int    idPointsTitleMsg = -1 ;
  108.     int    idPointsTypeTIcon[2] = -1 ;
  109.     int    idPointsCommandTIcon[3] = -1 ;
  110.     int    idPointsEditDBtn[6] = -1 ;
  111.     int    idPointsEditMsg[6] = -1 ;
  112.     int    idPointsDarkTIcon[2] = -1 ;
  113.     int    idPointsDarkMsg[2] = -1 ;
  114.  
  115. /*--------------------------------------------------------*/
  116. /*                 モジュール内定数・変数                 */
  117. /*--------------------------------------------------------*/
  118.  
  119.   /* 操作点ウィンドウ内での画像の位置 */
  120.     static int IMAGEX[2] = {48,48};
  121.     static int IMAGEY[2] = {68,274};
  122.  
  123.   /* 操作点の種別 */
  124.     #define    CPOINT_POINT    0
  125.     #define    CPOINT_LINE        1
  126.     #define    CPOINT_QUAD        2
  127.  
  128.   /* 操作点をあらわす構造体 */
  129.     typedef struct {
  130.         int        x[2],y[2];    /* A側、B側それぞれの座標 */
  131.         int        type;        /* CPOINT_POINT, ..LINE,..QUAD */
  132.         int        c1,c2;
  133.                 /* ↑接続している操作点の番号:
  134.                         CPOINT_POINT の場合 c1, c2 は無意味、
  135.                         CPOINT_LINE の場合、始点で c1=-1, 終点で c2=-1
  136.                         CPOINT_QUAD の場合、点1で c1=-1, 点4で c2=-1 */
  137.     } CPOINT;    /* 操作点(control point) */
  138.  
  139.   /* 操作点リスト */
  140.     LIST *plPoints = NULL;
  141.         #define    CP_NUM            list_getDataNum(plPoints)
  142.         #define    CP_GETDATA(n,p) \
  143.             { list_moveTo(plPoints,(n)); list_getData(plPoints,(p)); }
  144.         static int CP_INSERT(int n, CPOINT **p)
  145.          { list_moveTo(plPoints,n);  return list_insertData(plPoints,p); }
  146.     int curPoint = 0;    /* 現在選択中の操作点の番号 */
  147.  
  148.   /* 操作点設定ウィンドウ内の画像の大きさ */
  149.     #define    IMAGEWIDTH    240
  150.     #define    IMAGEHEIGHT    180
  151.   /* 操作点設定ウィンドウ内の画像を表す構造体 */
  152.   /* [0]:A側  [1]:B側 */
  153.     static IMAGE *piOriginal[2] = {NULL,NULL};    // オリジナル画像
  154.     static IMAGE *piDisplay[2] = {NULL,NULL};    // 表示用画像
  155.   /* 操作点ウィンドウ上で選んでいる「操作点タイプ」 */
  156.     static int pointType;
  157.   /* 操作点ウィンドウ上で選んでいる「操作点コマンド」 */
  158.     static int pointCommand;
  159.   /* CPOINT_LINE の場合、現在どの操作点を始点としているか */
  160.     static int nFromPoint = -1;
  161.  
  162.     static void points_checkActivity(int bRedraw);
  163.  
  164. /*--------------------------------------------------------*/
  165. /*                モジュールの初期化・終了                */
  166. /*--------------------------------------------------------*/
  167.  
  168.     int    init_points(void)
  169.     {
  170.         int i;
  171.         for (i=0; i<2; i++)
  172.         {
  173.             if ((piDisplay[i] = image_new(IMAGEWIDTH/2,IMAGEHEIGHT/2)) == NULL)
  174.                 return -1;
  175.         }
  176.         points_checkActivity(FALSE);
  177.         pointType = 1;
  178.         RM_initRadioButton(idPointsTypeTIcon,
  179.                            INTNUM(idPointsTypeTIcon), &pointType);
  180.         pointCommand = 0;
  181.         RM_initRadioButton(idPointsCommandTIcon,
  182.                            INTNUM(idPointsCommandTIcon), &pointCommand);
  183.         plPoints = list_new(sizeof(CPOINT*));
  184.         return 0;
  185.     }
  186.  
  187.     void end_points(void)
  188.     {
  189.         list_destroy(plPoints);
  190.     }
  191.  
  192. /*--------------------------------------------------------*/
  193. /*        ウィンドウ上のボタンの有効/無効チェック        */
  194. /*--------------------------------------------------------*/
  195.  
  196.     static void points_checkActivity(int bRedraw)
  197.     {
  198.         int i;
  199.         for (i=0; i<2; i++)
  200.         {
  201.             WINCLIP *pwclip;
  202.             if (piOriginal[i] == NULL)
  203.             {
  204.                 MMI_SendMessage(idPointsDarkTIcon[i], MM_ENABLE, 1, FALSE);
  205.                 RM_setChColor(idPointsDarkMsg[i], GRAY);
  206.             }
  207.             else
  208.             {
  209.                 MMI_SendMessage(idPointsDarkTIcon[i], MM_ENABLE, 1, TRUE);
  210.                 RM_setChColor(idPointsDarkMsg[i], BLACK);
  211.             }
  212.             if (bRedraw)
  213.             {
  214.                 WIN_beginUpDateObj(idPointsDarkTIcon[i], &pwclip);
  215.                 MMI_SendMessage(idPointsDarkTIcon[i], MM_SHOW, 0);
  216.                 MMI_SendMessage(idPointsDarkMsg[i], MM_SHOW, 0);
  217.                 WIN_endUpDateObj(pwclip);
  218.             }
  219.         }
  220.     }
  221.  
  222. /*--------------------------------------------------------*/
  223. /*                      操作点構造体                      */
  224. /*--------------------------------------------------------*/
  225.  
  226.     static CPOINT *cpoint_new(int type, int x, int y)
  227.     {
  228.         CPOINT *pcp;
  229.         if ((pcp = TL_calloc(1,sizeof(CPOINT))) == NULL)
  230.             return NULL;
  231.         pcp->type = type;
  232.         pcp->x[0] = pcp->x[1] = x;
  233.         pcp->y[0] = pcp->y[1] = y;
  234.         pcp->c1 = pcp->c2 = -1;
  235.         return pcp;
  236.     }
  237.  
  238.     static void cpoint_delete(CPOINT *pcp)
  239.     {
  240.         TL_free(pcp);
  241.     }
  242.  
  243. /*--------------------------------------------------------*/
  244. /*           画像上であるかどうかの座標チェック           */
  245. /*--------------------------------------------------------*/
  246.  
  247.     void points_whereis(int scrx, int scry, int *side, int *n)
  248.     // 返値 side: 0=A側  1=B側  -1=どちらでもない
  249.     //      n:    0=画像内  -1=画像外
  250.     {
  251.         EVENT ev;
  252.         ev.what = EVMOSDN;
  253.         ev.shift = SLEFTBTN;
  254.         ((POINT*)&ev.info)->x = scrx;
  255.         ((POINT*)&ev.info)->y = scry;
  256.         int id;
  257.         id = MMI_SendMessage(idDesktopSelectiveHyper, MM_ONPARTS, 1, &ev);
  258.         if (id != idPointsWin)
  259.             goto NOWHERE;
  260.         FRAME fr;
  261.         RM_getFrame(idPointsWin, &fr);
  262.         int i;
  263.         for (i=0; i<2; i++)
  264.         {
  265.             int ix,iy;
  266.             ix = fr.lupx + IMAGEX[i];
  267.             iy = fr.lupy + IMAGEY[i];
  268.             if (ix <= scrx && scrx < ix + IMAGEWIDTH &&
  269.                 iy <= scry && scry < iy + IMAGEHEIGHT)
  270.             {
  271.                 int wid,ht;
  272.                 if (piOriginal[i] == NULL)
  273.                     wid = 0, ht = 0;
  274.                 else
  275.                     image_getDispSize(piOriginal[i], IMAGEWIDTH, IMAGEHEIGHT,
  276.                                       &wid, &ht);
  277.                 if (ix <= scrx && scrx < ix+wid && iy <= scry && scry < iy+ht)
  278.                     { *side = i;  *n = 0;  return; }
  279.                 else
  280.                     { *side = i;  *n = -1;  return; }
  281.             }
  282.         }
  283.        NOWHERE:;
  284.         *side = -1;
  285.         *n = -1;
  286.     }
  287.  
  288.     static void getImageFrame(int side, FRAME *fr)
  289.     {
  290.         if (fr == NULL)
  291.             return;
  292.         RM_getFrame(idPointsWin, fr);
  293.         fr->lupx += IMAGEX[side];
  294.         fr->lupy += IMAGEY[side];
  295.         fr->rdwx = fr->lupx + IMAGEWIDTH - 1;
  296.         fr->rdwy = fr->lupy + IMAGEHEIGHT - 1;
  297.     }
  298.  
  299.     static int checkOnImage(int scrx,int scry,int *pimgx,int *pimgy)
  300.     /* -1:画像外  0:画像A 1:画像B */
  301.     /* 返値: *pimgx,*pimgy : 画像内での画面座標 */
  302.     {
  303.         FRAME fr;
  304.         RM_getFrame(idPointsWin, &fr);
  305.         int i;
  306.         for (i=0; i<2; i++)
  307.         {
  308.             int wid,ht;
  309.             if (piOriginal[i] == NULL)
  310.               wid = 0, ht = 0;
  311.             else
  312.               image_getDispSize(piOriginal[i],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
  313.             if (fr.lupx+IMAGEX[i] <= scrx && scrx < fr.lupx+IMAGEX[i]+wid &&
  314.                 fr.lupy+IMAGEY[i] <= scry && scry < fr.lupy+IMAGEY[i]+ht)
  315.             {
  316.                 *pimgx = scrx - (fr.lupx+IMAGEX[i]);
  317.                 *pimgy = scry - (fr.lupy+IMAGEY[i]);
  318.                 return i;
  319.             }
  320.         }
  321.         return -1;
  322.     }
  323.  
  324.     #define    MAXDIF    4        /* ±MAXDIF 以内の座標なら「操作点の上」とみなす */
  325.  
  326.     static void getPointXY(int side, int num, int *scrx, int *scry)
  327.     // ある操作点の、画面上での座標を求める。
  328.     {
  329.         FRAME fr;
  330.         CPOINT *pcp;
  331.         RM_getFrame(idPointsWin, &fr);
  332.         list_moveTo(plPoints, num);
  333.         list_getData(plPoints, &pcp);
  334.         *scrx = fr.lupx + IMAGEX[side] + pcp->x[side];
  335.         *scry = fr.lupy + IMAGEY[side] + pcp->y[side];
  336.     }
  337.  
  338.     static int checkOnPoint(int side, int imagex, int imagey, int *pDx, int *pDy)
  339.     {
  340.         int n;
  341.         for (list_top(plPoints),n=0; !list_isOut(plPoints);
  342.              list_next(plPoints),n++)
  343.         {
  344.             CPOINT *pcp;
  345.             list_getData(plPoints, &pcp);
  346.             if (pcp->x[side]-4 <= imagex && imagex <= pcp->x[side]+4 &&
  347.                 pcp->y[side]-4 <= imagey && imagey <= pcp->y[side]+4)
  348.             {
  349.                 *pDx = pcp->x[side] - imagex;
  350.                 *pDy = pcp->y[side] - imagey;
  351.                 return n;
  352.             }
  353.         }
  354.         return -1;
  355.     }
  356.  
  357. /*--------------------------------------------------------*/
  358. /*                      操作点の表示                      */
  359. /*--------------------------------------------------------*/
  360.  
  361.     static void setClipImage(int side)
  362.     {
  363.         int wid,ht;
  364.         if (piOriginal[side] != NULL)
  365.           image_getDispSize(piOriginal[side],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
  366.         else
  367.           wid = IMAGEWIDTH, ht = IMAGEHEIGHT;
  368.         FRAME fr;
  369.         RM_getFrame(idPointsWin, &fr);
  370.         fr.lupx = fr.lupx + IMAGEX[side];
  371.         fr.lupy = fr.lupy + IMAGEY[side];
  372.         fr.rdwx = fr.lupx + wid - 1;
  373.         fr.rdwy = fr.lupy + ht - 1;
  374.         RM_setClipAnyFrame(idPointsWin, &fr);
  375.     }
  376.  
  377.     static char grpPoint[] =
  378.     // 9×9ドット、透過色0
  379.     {
  380.         0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00,
  381.         0x00,0xf8,0xff,0x08,0x00,0x00,0x00,0x00,
  382.         0x80,0xff,0xff,0x8f,0x00,0x00,0x00,0x00,
  383.         0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
  384.         0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
  385.         0xf8,0xff,0xff,0xff,0x08,0x00,0x00,0x00,
  386.         0x80,0xff,0xff,0x8f,0x00,0x00,0x00,0x00,
  387.         0x00,0xf8,0xff,0x08,0x00,0x00,0x00,0x00,
  388.         0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00
  389.     };
  390.  
  391.     static char grpPoint2[] =
  392.     // 選択中の操作点。9×9ドット、透過色0
  393.     {
  394.         0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00,
  395.         0x00,0xa8,0xaa,0x08,0x00,0x00,0x00,0x00,
  396.         0x80,0xaa,0xaa,0x8a,0x00,0x00,0x00,0x00,
  397.         0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
  398.         0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
  399.         0xa8,0xaa,0xaa,0xaa,0x08,0x00,0x00,0x00,
  400.         0x80,0xaa,0xaa,0x8a,0x00,0x00,0x00,0x00,
  401.         0x00,0xa8,0xaa,0x08,0x00,0x00,0x00,0x00,
  402.         0x00,0x80,0x88,0x00,0x00,0x00,0x00,0x00
  403.     };
  404.  
  405.     static FRAME _frWin;
  406.  
  407.     #define    SX(side,x)        (_frWin.lupx + IMAGEX[side] + (x))
  408.     #define    SY(side,y)        (_frWin.lupy + IMAGEY[side] + (y))
  409.  
  410.     static void _dispPoints_init(void)
  411.     {
  412.         RM_getFrame(idPointsWin, &_frWin);
  413.     }
  414.  
  415.     #define    DRAW_NORMAL        0
  416.     #define    DRAW_XOR        1
  417.     #define    DRAW_ERASE        2
  418.  
  419.     static void _drawPoint(int side, int n, int mode)
  420.     {
  421.         if (n < 0 || CP_NUM <= n)
  422.             return;
  423.         CPOINT *cp;
  424.         CP_GETDATA(n, &cp);
  425.         int x,y;
  426.         char *grp;
  427.         x = SX(side, cp->x[side]);
  428.         y = SY(side, cp->y[side]);
  429.         grp = (n == curPoint ? grpPoint2 : grpPoint);
  430.         if (mode == DRAW_NORMAL)
  431.         {
  432.             WGB_PUTBLOCK_MATTE(guiEgbPtr, grp, x-4,y-4, 9,9);
  433.         }
  434.         else if (mode == DRAW_XOR)
  435.         {
  436.             WGB_PUTBLOCK(guiEgbPtr, grp, x-4,y-4, 9,9, XOR);
  437.         }
  438.         else if (mode == DRAW_ERASE)
  439.         {
  440.             WGB_RBOXFILL(guiEgbPtr, x-4,y-4, 9,9, 0,0);
  441.         }
  442.     }
  443.  
  444.     #define    RUB_PREV    1
  445.     #define    RUB_NEXT    2
  446.  
  447.     static void _drawRubber(int side,int n,int flag,int mode)
  448.     // flag:RUB_PREV, RUB_NEXT
  449.     // mode:0=消去  1=描画
  450.     {
  451.         if (n < 0 || CP_NUM <= n)
  452.             return;
  453.         CPOINT *cp,*cp2;
  454.         CP_GETDATA(n, &cp);
  455.         if (cp->type != CPOINT_LINE)
  456.             return;
  457.         int i;
  458.         for (i=0; i<2; i++)
  459.         {
  460.             if ((i == 0 ? ((flag&RUB_PREV)!=0 && cp->c1 >= 0) :
  461.                           ((flag&RUB_NEXT)!=0 && cp->c2 >= 0)))
  462.             {
  463.                 CP_GETDATA((i == 0 ? cp->c1 : cp->c2), &cp2);
  464.                 if (cp2 != NULL)
  465.                 {
  466.                     #define    X(pCp)        SX(side, (pCp)->x[side])
  467.                     #define    Y(pCp)        SY(side, (pCp)->y[side])
  468.                     if (mode == DRAW_NORMAL)
  469.                      { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),RED,0); }
  470.                     else if (mode == DRAW_XOR)
  471.                      { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),RED,XOR); }
  472.                     else if (mode == DRAW_ERASE) /* ?? */
  473.                      { WGB_LINE(guiEgbPtr,X(cp),Y(cp),X(cp2),Y(cp2),0,0); }
  474.                     #undef Y
  475.                     #undef X
  476.                 }
  477.             }
  478.         }
  479.     }
  480.  
  481.     static void dispPoints(void)
  482.     {
  483.         int i;
  484.         MG_mosDisp(2);
  485.         RM_setOriginZero();
  486.         _dispPoints_init();
  487.         for (i=0; i<2; i++)
  488.         {
  489.           /* いったんすべての操作点を消す */
  490.             int wid,ht;
  491.             image_getDispSize(piOriginal[i],IMAGEWIDTH,IMAGEHEIGHT,&wid,&ht);
  492.             if (wid == 0 || ht == 0)
  493.                 continue;
  494.             setClipImage(i);
  495.             WGB_RBOXFILL(guiEgbPtr, SX(i,0), SY(i,0), wid, ht, 0, 0);
  496.           /* 線分操作点の連結線を描画 */
  497.             int n;
  498.             for (n=0; n<CP_NUM; n++)
  499.                 _drawRubber(i, n, RUB_NEXT, DRAW_NORMAL);
  500.           /* 操作点を描画 */
  501.             for (n=0; n<CP_NUM; n++)
  502.                 _drawPoint(i, n, DRAW_NORMAL);
  503.             RM_recoverClipVisible();
  504.         }
  505.         RM_recoverOrigin();
  506.         MG_mosDisp(3);
  507.     }
  508.  
  509.     #undef SX
  510.     #undef SY
  511.  
  512. /*--------------------------------------------------------*/
  513. /*              操作点ウィンドウ内の画像表示              */
  514. /*--------------------------------------------------------*/
  515.  
  516.     static void dispImages(void)
  517.     {
  518.         static char *msg = "画像が読み込まれていません";
  519.         #define    SX    ((IMAGEWIDTH-12*13)/2)
  520.         #define    SY    ((IMAGEHEIGHT-12)/2)
  521.         FRAME fr;
  522.         MG_mosDisp(2);
  523.         RM_getFrame(idPointsWin, &fr);
  524.         RM_setOriginZero();
  525.         WINCLIP *pwc;
  526.         RM_setClipWinUser(idPointsWin, &pwc);
  527.         int i;
  528.         for (i=0; i<2; i++)
  529.         {
  530.             int x,y;
  531.             x = fr.lupx + IMAGEX[i];
  532.             y = fr.lupy + IMAGEY[i];
  533.             WGB_RBOXFILL(guiEgbPtr,x+IMAGEWIDTH-6*12,y+IMAGEHEIGHT+2,
  534.                          6*12,12,WINBACK,0);
  535.             WGB_RBOXFILL(guiEgbPtr,x,y-2-12,6*12,12,WINBACK,0);
  536.             if (piOriginal[i] != NULL)
  537.             {
  538.                 image_disp(piDisplay[i],x,y,IMAGEWIDTH, IMAGEHEIGHT);
  539.                 if (i==0)
  540.                 {
  541.                     char msg[40];
  542.                     sprintf(msg,"↑(%d×%d)",
  543.                             piOriginal[i]->virwid,piOriginal[i]->virht);
  544.                     RM_putstring12(guiEgbPtr,x+IMAGEWIDTH-6*strlen(msg),
  545.                                    y+IMAGEHEIGHT+2, msg, BLACK, 0);
  546.                 }
  547.                 else
  548.                 {
  549.                     char msg[40];
  550.                     sprintf(msg,"(%d×%d)↓",
  551.                             piOriginal[i]->virwid,piOriginal[i]->virht);
  552.                     RM_putstring12(guiEgbPtr,x,y-2-12,msg, BLACK, 0);
  553.                 }
  554.             }
  555.             else
  556.             {
  557.                 WGB_RBOXFILL(guiEgbPtr,x,y,IMAGEWIDTH,IMAGEHEIGHT,WINBACK, 0);
  558.                 WGB_RBOXLINE(guiEgbPtr,x,y,IMAGEWIDTH,IMAGEHEIGHT,BLACK, 0);
  559.                 RM_putstring12(guiEgbPtr,x+SX,y+SY,msg, BLACK,0);
  560.             }
  561.         }
  562.         RM_resetClipWinUser(pwc);
  563.         RM_recoverOrigin();
  564.         dispPoints();
  565.         MG_mosDisp(3);
  566.         #undef SX
  567.         #undef SY
  568.     }
  569.  
  570. /*--------------------------------------------------------*/
  571. /*           操作点の作成/移動/削除のサブ処理           */
  572. /*--------------------------------------------------------*/
  573.  
  574.   /* 操作点の作成 */
  575.  
  576.     static int makeControlPoint(int type, int imgx, int imgy)
  577.     /*
  578.         タイプ type (CPOINT_POINT / CPOINT_LINE) の操作点を
  579.         画像上の表示座標(imgx,imgy) の位置に作成し、
  580.         画面表示をそれにあわせて更新する。
  581.         返値: 作成した操作点の番号 (失敗時 -1)
  582.     */
  583.     {
  584.         CPOINT *pcp;
  585.         if ((pcp = cpoint_new(type,imgx,imgy)) == NULL)
  586.         {
  587.             alert_noMemory("操作点の作成");
  588.             return -1;
  589.         }
  590.         int n = CP_NUM;
  591.         CP_INSERT(n, &pcp);
  592.         curPoint = n;
  593.         if (type == CPOINT_LINE)
  594.         {
  595.             if (nFromPoint >= 0)
  596.             {
  597.                 CPOINT *pcp2;
  598.                 CP_GETDATA(nFromPoint, &pcp2);
  599.                 pcp2->c2 = n, pcp->c1 = nFromPoint;    // 線分操作点のリンク
  600.             }
  601.             nFromPoint = n;
  602.         }
  603.         dispPoints();
  604.         return n;
  605.     }
  606.  
  607.   /* 操作点の移動 */
  608.  
  609.     static void moveControlPoint(int side,int num,int dx,int dy)
  610.     /* side,num: A/B選択と、操作点番号 */
  611.     /* (dx,dy)=マウス座標から見た操作点の固定変位 */
  612.     /* 呼ばれるときにはマウスカーソルは表示されていること */
  613.     {
  614.         int moscsr;
  615.         EVENT *pev;
  616.         RM_setOriginZero();
  617.         setClipImage(side);
  618.       /* カレント操作点を、クリックした操作点に設定、画面更新 */
  619.         curPoint = num;
  620.         dispPoints(); /* もっと効率よい画面更新はないか? */
  621.         MG_mosDisp(2);
  622.         _dispPoints_init();
  623.         _drawPoint(side, num, DRAW_ERASE);
  624.         _drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_ERASE);
  625.         MG_PushPtr(MOSICON_PICK, &moscsr);
  626.         MG_mosDisp(3);
  627.       /* ドラッグしている間のループ */
  628.         do {
  629.             int msx,msy;
  630.             MG_mosDisp(2);
  631.             _drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_XOR);
  632.             _drawPoint(side, num, DRAW_XOR);
  633.             MG_mosDisp(3);
  634.             do {
  635.                 MMI_iosense() ;
  636.             } while ((MMI_GetEvnt(EVMOSDRAG|EVMOSUP, &pev)) < NOERR);
  637.             MG_mosDisp(2);
  638.             _drawPoint(side,num,DRAW_XOR);
  639.             _drawRubber(side,num,RUB_PREV|RUB_NEXT,DRAW_XOR);
  640.             MG_mosDisp(3);
  641.             msx = *((short *)&(pev->info)) ;
  642.             msy = *(((short *)&(pev->info)) + 1) ;
  643.             if (pev->what == EVMOSDRAG)
  644.             {
  645.                 int imx,imy;
  646.                 if (checkOnImage(msx,msy,&imx,&imy) == side)
  647.                 {
  648.                   /* 操作点をマウスにあわせ移動 */
  649.                     CPOINT *pcp;
  650.                     CP_GETDATA(num, &pcp);
  651.                     pcp->x[side] = imx + dx;
  652.                     pcp->y[side] = imy + dy;
  653.                 }
  654.             }
  655.         } while ((pev->what != EVMOSUP) || (pev->shift & SLEFTBTN) == 0);
  656.         dispPoints();
  657.         MG_PopPtr(moscsr);
  658.         RM_recoverClipVisible();
  659.         RM_recoverOrigin();
  660.     }
  661.  
  662.   /* 操作点の削除 */
  663.  
  664.     static void deleteControlPoint(int side,int num)
  665.     /* side,num: A/B選択と、操作点番号 */
  666.     /* 呼ばれるときにはマウスカーソルは表示されていること */
  667.     {
  668.         int moscsr;
  669.         int msx,msy;
  670.         EVENT *pev;
  671.       /* カレント操作点を、クリックされた操作点にする */
  672.         curPoint = num;
  673.         dispPoints();    /* もっと効率よい画面更新はないか? */
  674.         MG_PushPtr(MOSICON_POINT, &moscsr);
  675.       /* ドラッグ操作 */
  676.         do {
  677.             do {
  678.                 MMI_iosense() ;
  679.             } while ((MMI_GetEvnt(EVMOSDRAG|EVMOSUP, &pev)) < NOERR);
  680.             msx = *((short *)&(pev->info)) ;
  681.             msy = *(((short *)&(pev->info)) + 1) ;
  682.         } while ((pev->what != EVMOSUP) || (pev->shift & SLEFTBTN) == 0);
  683.       /* ドラッグ操作された後もマウスが同じ操作点を指していたら削除 */
  684.         FRAME fr;
  685.         RM_getFrame(idPointsWin, &fr);
  686.         int cx,cy;
  687.         getPointXY(side,num,&cx,&cy);
  688.         if (abs(msx-cx) <= MAXDIF && abs(msy-cy) <= MAXDIF)
  689.         {
  690.             CPOINT *pcp;
  691.             CP_GETDATA(num, &pcp);
  692.           /* 線分操作点だったときのリンクの修正 */
  693.             if (pcp->type == CPOINT_LINE)
  694.             {
  695.                 CPOINT *pcp2;
  696.                 if (pcp->c1 >= 0)
  697.                     { CP_GETDATA(pcp->c1, &pcp2);  pcp2->c2 = pcp->c2; }
  698.                 if (pcp->c2 >= 0)
  699.                     { CP_GETDATA(pcp->c2, &pcp2);  pcp2->c1 = pcp->c1; }
  700.             }
  701.           /* 操作点の削除 */
  702.             list_moveTo(plPoints, num);
  703.             list_deleteData(plPoints);
  704.             cpoint_delete(pcp);
  705.           /* 他の線分操作点のリンクの修正 */
  706.             int n;
  707.             for (n=0; n<CP_NUM; n++)
  708.             {
  709.                 CPOINT *pcp2;
  710.                 CP_GETDATA(n,&pcp2);
  711.                 if (pcp2->type == CPOINT_LINE)
  712.                 {
  713.                     if (pcp2->c1 >= num)  pcp2->c1--;
  714.                     if (pcp2->c2 >= num)  pcp2->c2--;
  715.                 }
  716.             }
  717.           /* 選択中の操作点番号の更新 */
  718.             if (curPoint > num)
  719.                 curPoint--;
  720.         }
  721.       /* 画面表示更新 */
  722.         dispPoints();    /* もっと効率よい画面更新はないか? */
  723.         MG_PopPtr(moscsr);
  724.     }
  725.  
  726. /*--------------------------------------------------------*/
  727. /*                      操作点の作成                      */
  728. /*--------------------------------------------------------*/
  729.  
  730.     static void points_makeNewPoints(EVENT *pev)
  731.     {
  732.         if (pointCommand != 0)
  733.             return;
  734.       /* マウスポインタの位置のチェック */
  735.         POINT pt;
  736.         pt = *(POINT*)&pev->info;
  737.         int side,rx,ry;
  738.         if ((side = checkOnImage(pt.x, pt.y, &rx,&ry)) < 0)
  739.             return;        /* ポインタが画像上にない */
  740.         int dx,dy;
  741.         if (checkOnPoint(side,rx,ry,&dx,&dy) >= 0)
  742.             return;        /* ポインタが既存の操作点上にある */
  743.       /* 操作点タイプ別の処理 */
  744.         RM_setOriginZero();
  745.         setClipImage(side);
  746.         if (pointType == CPOINT_POINT)
  747.             makeControlPoint(CPOINT_POINT, rx,ry);
  748.         else if (pointType == CPOINT_LINE)
  749.         {
  750.             nFromPoint = -1;
  751.             int idPoint;
  752.             if ((idPoint = makeControlPoint(CPOINT_LINE, rx,ry)) < 0)
  753.                 goto END_MAKELINECPOINT;
  754.             int fromx,fromy;
  755.             int msx,msy;
  756.             getPointXY(side, idPoint, &fromx, &fromy);
  757.             msx = fromx, msy = fromy;
  758.             for (;;)
  759.             {
  760.                 MG_mosDisp(2);
  761.                 WGB_LINE(guiEgbPtr, fromx,fromy,msx,msy,RED, XOR);
  762.                 MG_mosDisp(3);
  763.                 do {
  764.                     MMI_iosense() ;
  765.                 } while ((MMI_GetEvnt(EVMOSMOVE|EVMOSDRAG|EVMOSDN, &pev))
  766.                          < NOERR);
  767.                 MG_mosDisp(2);
  768.                 WGB_LINE(guiEgbPtr, fromx,fromy,msx,msy,RED, XOR);
  769.                 MG_mosDisp(3);
  770.                 msx = *((short *)&(pev->info)) ;
  771.                 msy = *(((short *)&(pev->info)) + 1) ;
  772.                 if (pev->what == EVMOSDN && (pev->shift & SRIGHTBTN) != 0)
  773.                     break;    // 右クリックされたので終了
  774.                 if (pev->what == EVMOSDN && (pev->shift & SLEFTBTN) != 0)
  775.                 {
  776.                     int imx,imy;
  777.                     if (checkOnImage(msx,msy,&imx,&imy) == side)
  778.                     {
  779.                         checkOnPoint(side,imx,imy,&dx,&dy);
  780.                         makeControlPoint(CPOINT_LINE, imx,imy);
  781.                         fromx = msx, fromy = msy;
  782.                     }
  783.                 }
  784.             }
  785.             nFromPoint = -1;
  786.            END_MAKELINECPOINT:;
  787.         }
  788.         RM_recoverClipVisible();
  789.         RM_recoverOrigin();
  790.     }
  791.  
  792. /*--------------------------------------------------------*/
  793. /*       操作点設定ウィンドウ内へ静止画像を読み込む       */
  794. /*--------------------------------------------------------*/
  795.  
  796.     void points_storeImage(int side, IMAGE *im)
  797.     {
  798.         if (side < 0 || 1 < side)
  799.             { printf("points_storeImage: internal error!\n");
  800.               return; }
  801.         if (piOriginal[side] != NULL)
  802.             image_delete(piOriginal[side]);
  803.         piOriginal[side] = im;
  804.         image_zoomdown(piDisplay[side], piOriginal[side]);
  805.         dispImages();
  806.         points_checkActivity(TRUE);
  807.     }
  808.  
  809.     void points_loadImage(int side)
  810.     /* side: 0=A側   1=B側 */
  811.     {
  812.         int ret;
  813.         static char alertTitle[] = "静止画読込(操作点設定ウィンドウ)";
  814.         char pathbuf[100];
  815.         ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
  816.                                "静止画の読込", "読込", "取消",
  817.                                "*.TIF", FDG_FILEONLY, pathbuf);
  818.         if (ret != 0)
  819.             return;    // 「取消」
  820.         TIFFinfo tiffinfo;
  821.         if (TIFFgetinfo(pathbuf, &tiffinfo) != 0)
  822.         {
  823.             char strbuf[200];
  824.             sprintf(strbuf, "ファイル %s が見つかりません", pathbuf);
  825.             dispAlertMessage(alertTitle, strbuf);
  826.             return;
  827.         }
  828.         if (tiffinfo.pixelsize != MORPH_PIXELSIZE)
  829.         {
  830.             char strbuf[200];
  831.             sprintf(strbuf, "ファイル %s は3万色画像ではない"
  832.                     "ので読み込めません", pathbuf);
  833.             dispAlertMessage(alertTitle, strbuf);
  834.             return;
  835.         }
  836.         IMAGE *im;
  837.         if ((im = image_new(tiffinfo.xlen, tiffinfo.ylen)) == NULL)
  838.             { alert_noMemory(alertTitle);  return; }
  839.         int moscsr;
  840.         MG_PushPtr(MOSICON_WAIT, &moscsr);
  841.         ret = image_loadTIFF(im, pathbuf);
  842.         MG_PopPtr(moscsr);
  843.         if (ret != 0)
  844.             { dispAlertMessage(alertTitle, "ファイル読み込みに失敗しました");
  845.               return; }
  846.         points_storeImage(side, im);
  847.     }
  848.  
  849. /*--------------------------------------------------------*/
  850. /*                    モーフィング処理                    */
  851. /*--------------------------------------------------------*/
  852.  
  853.     static void dispXY2imageXY(int dispx,int dispy,int dispwid,int dispht,
  854.                                int imagewid, int imageht, int *ix,int *iy)
  855.     {
  856.         int imx,imy;
  857.         imx = ((imagewid-1)*dispx + (dispwid-1)/2) / (dispwid-1);
  858.         imy = ((imageht -1)*dispy + (dispht -1)/2) / (dispht -1);
  859.         *ix = imx;
  860.         *iy = imy;
  861.     }
  862.  
  863.     int points_makeMorphPoints(LIST *plPOINT, LIST *plLINE)
  864.     /* モーフィング処理のための操作点(境界点)情報作成 */
  865.     /* plPOINT,plLINE: 操作点情報を登録するための空リスト */
  866.     /* このモジュール内の plPoints に登録されている操作点をもとに、
  867.        点操作点、線分操作点の情報を作成する。
  868.        新たに作成したリストは、plPOINT, plLINE に登録される */
  869.     {
  870.         static char alertTitle[] = "モーフィング/変形アニメ作成";
  871.         int imwid,imht;
  872.         imwid = piOriginal[0]->width;
  873.         imht  = piOriginal[0]->height;
  874.       /* 画像の表示サイズを求める */
  875.         int wid[2],ht[2];
  876.         image_getDispSize(piOriginal[0],IMAGEWIDTH,IMAGEHEIGHT,&wid[0],&ht[0]);
  877.         image_getDispSize(piOriginal[1],IMAGEWIDTH,IMAGEHEIGHT,&wid[1],&ht[1]);
  878.         if (imwid < 2 || imht < 2 ||
  879.             wid[0] < 2 || ht[0] < 2 || wid[1] < 2 || ht[1] < 2)
  880.             return -1;    // ★「なぜか画像が小さすぎる」!内部エラーかも
  881.       /* 各操作点を画像内での座標に変換しながら新たにリスト作成 */
  882.         #define    GETXY(cp,side,px,py)                                        \
  883.             dispXY2imageXY((cp)->x[side],(cp)->y[side],wid[side],ht[side],    \
  884.                            imwid,imht,px,py);
  885.         int n;
  886.         list_top(plPOINT);
  887.         for (n=0; n<CP_NUM; n++)
  888.         {
  889.             CPOINT *pcp;
  890.             CP_GETDATA(n, &pcp);
  891.             if (!(pcp->type == CPOINT_POINT ||
  892.                   (pcp->type == CPOINT_LINE && pcp->c1 < 0 && pcp->c2 < 0)))
  893.                 continue;
  894.             MORPH_POINT mp;
  895.             GETXY(pcp,0,&mp.from.x,&mp.from.y);
  896.             GETXY(pcp,1,&mp.to.x,&mp.to.y);
  897.             if (list_insertData(plPOINT, &mp) != 0)
  898.                 { alert_noMemory(alertTitle);
  899.                   return -1; }
  900.             list_next(plPOINT);
  901.         }
  902.         list_top(plLINE);
  903.         for (n=0; n<CP_NUM; n++)
  904.         {
  905.             CPOINT *pcp;
  906.             CP_GETDATA(n,&pcp);
  907.             if (pcp->type == CPOINT_LINE && pcp->c1 < 0 && pcp->c2 >= 0)
  908.             {
  909.                 CPOINT *pcp2;
  910.                 for (;pcp->c2>=0;pcp=pcp2)
  911.                 {
  912.                    CP_GETDATA(pcp->c2, &pcp2);    // 終点の操作点
  913.                    MORPH_LINE ml;
  914.                    GETXY(pcp, 0,&ml.from1.x,&ml.from1.y);
  915.                    GETXY(pcp2,0,&ml.from2.x,&ml.from2.y);
  916.                    GETXY(pcp, 1,&ml.to1.x,&ml.to1.y);
  917.                    GETXY(pcp2,1,&ml.to2.x,&ml.to2.y);
  918.                    if (list_insertData(plLINE, &ml) != 0)
  919.                      { alert_noMemory(alertTitle);
  920.                        return -1; }
  921.                    list_next(plLINE);
  922.                 }
  923.             }
  924.         }
  925.         #undef GETXY
  926.         #if 0
  927.             printf("morphing: Num(plPOINT)=%d\n", list_getDataNum(plPOINT));
  928.             for (list_top(plPOINT); !list_isOut(plPOINT); list_next(plPOINT))
  929.             {
  930.                 MORPH_POINT mp;
  931.                 list_getData(plPOINT,&mp);
  932.                 printf("  %d,%d,%d,%d\n",mp.from.x,mp.from.y,mp.to.x,mp.to.y);
  933.             }
  934.         #endif
  935.         return 0;
  936.     }
  937.  
  938.     int points_checkMorphImages(void)
  939.     {
  940.         if (piOriginal[0] == NULL || piOriginal[1] == NULL)
  941.             return POINTS_IMAGE_NO_THERE;
  942.         int imwid,imht;    // 画像のサイズ
  943.         imwid = piOriginal[0]->width;
  944.         imht  = piOriginal[0]->height;
  945.         if (imwid != piOriginal[1]->width || imht != piOriginal[1]->height)
  946.             return POINTS_IMAGE_MISMATCH_SIZE;
  947.         return 0;
  948.     }
  949.  
  950.     void points_getImageSize(int *pwid,int *pht)
  951.     {
  952.         int imwid,imht;
  953.         if (piOriginal[0] != NULL)
  954.             imwid = piOriginal[0]->width, imht  = piOriginal[0]->height;
  955.         else if (piOriginal[1] != NULL)
  956.             imwid = piOriginal[1]->width, imht  = piOriginal[1]->height;
  957.         else
  958.             return;
  959.         if (pwid != NULL)
  960.             *pwid = imwid;
  961.         if (pht != NULL)
  962.             *pht  = imht;
  963.     }
  964.  
  965.     int morphGetFromPixel(fxp x, fxp y, int *r,int *g,int *b)
  966.     {
  967.         unsigned short c;
  968.         int tx,ty;
  969.         int ret;
  970.         tx = FX2I(x);
  971.         ty = FX2I(y);
  972.         unsigned short *image;
  973.         image = (unsigned short *)piOriginal[0]->image;
  974.         c = image[piOriginal[0]->width * ty + tx];
  975.         ret = 0;
  976.         if (c == image[0])
  977.             ret = -1;
  978.         *g = (c >> 10) & 0x1f;
  979.         *r = (c >>  5) & 0x1f;
  980.         *b = (c      ) & 0x1f;
  981.         return ret;
  982.     }
  983.  
  984.     int morphGetToPixel(fxp x, fxp y, int *r,int *g,int *b)
  985.     {
  986.         int ret;
  987.         unsigned short c, *image;
  988.         int tx,ty;
  989.         tx = FX2I(x);
  990.         ty = FX2I(y);
  991.         image = (unsigned short *)piOriginal[1]->image;
  992.         c = image[piOriginal[1]->width * ty + tx];
  993.         ret = 0;
  994.         if (c == image[0])
  995.             ret = -1;
  996.         *g = (c >> 10) & 0x1f;
  997.         *r = (c >>  5) & 0x1f;
  998.         *b = (c      ) & 0x1f;
  999.         return ret;
  1000.     }
  1001.  
  1002. /*--------------------------------------------------------*/
  1003. /*                 操作点の読み込み・保存                 */
  1004. /*--------------------------------------------------------*/
  1005.  
  1006.     int        points_checkLoadPoints(void)
  1007.     {
  1008.         if (piOriginal[0] == NULL && piOriginal[1] == NULL)
  1009.             return -1;
  1010.         else
  1011.             return 0;
  1012.     }
  1013.  
  1014.     static char pointFileHeader[32+1] = "DolphMorph PointInfo 1.0        ";
  1015.  
  1016.     void points_loadPoints(void)
  1017.     {
  1018.         static char ALERTTITLE[] = "操作点の読込";
  1019.         int ret;
  1020.         int i;
  1021.         char pathbuf[100];
  1022.         ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
  1023.                                "操作点読込", "読込", "取消", "*.MCP",
  1024.                                FDG_FILEONLY, pathbuf);
  1025.         if (ret != 0)
  1026.             return;    // 「取消」
  1027.         FILE *fp;
  1028.         if ((fp = fopen(pathbuf, "rb")) == NULL)
  1029.         {
  1030.             char strbuf[200];
  1031.             sprintf(strbuf, "ファイル %s が見つかりません", pathbuf);
  1032.             dispAlertMessage(ALERTTITLE, strbuf);
  1033.             return;
  1034.         }
  1035.         int moscsr;
  1036.         char readbuf[200];
  1037.         MG_PushPtr(MOSICON_WAIT, &moscsr);
  1038.         fread(readbuf, 1,32, fp);
  1039.         if (memcmp(readbuf, pointFileHeader, 32) != 0)
  1040.         {
  1041.             fclose(fp);
  1042.             char strbuf[200];
  1043.             sprintf(strbuf, "ファイル %s は操作点情報ファイルではないので"
  1044.                     "読み込めません", pathbuf);
  1045.             dispAlertMessage(ALERTTITLE, strbuf);
  1046.             goto READEND;
  1047.         }
  1048.         fread(readbuf, 4,1, fp);
  1049.         int num;
  1050.         num = *(int*)readbuf;
  1051.         int idx = CP_NUM;
  1052.         for (i=0; i<num; i++)
  1053.         {
  1054.             CPOINT readcp, *pcp;
  1055.             fread(&readcp, sizeof(CPOINT), 1, fp);
  1056.             if ((pcp = cpoint_new(CPOINT_POINT,0,0)) == NULL)
  1057.             {
  1058.                 alert_noMemory(ALERTTITLE);
  1059.                 break;
  1060.             }
  1061.             *pcp = readcp;
  1062.             if (pcp->c1 >= 0)
  1063.                 pcp->c1 += idx;
  1064.             if (pcp->c2 >= 0)
  1065.                 pcp->c2 += idx;
  1066.             if (CP_INSERT(idx+i, &pcp) != 0)
  1067.             {
  1068.                 alert_noMemory(ALERTTITLE);
  1069.                 break;
  1070.             }
  1071.         }
  1072.         fclose(fp);
  1073.         MG_PopPtr(moscsr);
  1074.        READEND:;
  1075.         dispImages();
  1076.         desktop_checkActivity();
  1077.     }
  1078.  
  1079.     int points_checkSavePoints(void)
  1080.     {
  1081.         if (CP_NUM > 0)
  1082.             return 0;
  1083.         else
  1084.             return -1;
  1085.     }
  1086.     
  1087.     void points_savePoints(void)
  1088.     {
  1089.         static char alertTitle[] = "操作点の保存";
  1090.         int ret;
  1091.         int i;
  1092.         char pathbuf[100],pathbuf2[100];
  1093.         if (CP_NUM <= 0)
  1094.         {
  1095.             dispAlertMessage("操作点の保存", "操作点が作成されていないので"
  1096.                              "保存できません");
  1097.             return;
  1098.         }
  1099.         ret = RM_callSimpleFDG(idDesktopAlertHyper, idDesktopSelectiveHyper,
  1100.                                "操作点保存", "保存", "取消", "*.MCP",
  1101.                                FDG_FILEONLY|FDG_TEXT, pathbuf);
  1102.         if (ret != 0)
  1103.             return;    // 「取消」
  1104.         strcpy(pathbuf2,pathbuf);
  1105.         trans_fname_ext(pathbuf, pathbuf2, "MCP");
  1106.         if (fexist(pathbuf))
  1107.         {
  1108.             char strbuf[200];
  1109.             sprintf(strbuf, "ファイル %s がすでに存在しています。"
  1110.                     "上書きしますか?", pathbuf);
  1111.             if (dispCheckMessage(alertTitle, strbuf, "上書き") != 0)
  1112.                 return;
  1113.         }
  1114.         FILE *fp;
  1115.         if ((fp = fopen(pathbuf, "wb")) == NULL)
  1116.         {
  1117.             char strbuf[200];
  1118.             sprintf(strbuf, "ファイル %s に書き込むことができません", pathbuf);
  1119.             dispAlertMessage(alertTitle, strbuf);
  1120.             return;
  1121.         }
  1122.         int moscsr;
  1123.         MG_PushPtr(MOSICON_WAIT, &moscsr);
  1124.         fwrite(pointFileHeader, 1,32, fp);
  1125.         char writebuf[4];
  1126.         *(int*)writebuf = CP_NUM;    // int=4bytes, big endian 前提……
  1127.         fwrite(writebuf, 4,1, fp);
  1128.         for (i=0; i<CP_NUM; i++)
  1129.         {
  1130.             CPOINT *pcp;
  1131.             CP_GETDATA(i, &pcp);
  1132.             fwrite(pcp, sizeof(CPOINT), 1, fp);
  1133.         }
  1134.         fclose(fp);
  1135.         MG_PopPtr(moscsr);
  1136.         desktop_checkActivity();
  1137.     }
  1138.  
  1139.     int        points_checkClearPoints(void)
  1140.     {
  1141.         if (CP_NUM > 0)
  1142.             return 0;
  1143.         else
  1144.             return -1;
  1145.     }
  1146.  
  1147.     void points_clearPoints(void)
  1148.     {
  1149.         static char alertTitle[] = "操作点のクリア";
  1150.         if (dispCheckMessage(alertTitle, "操作点をすべて消去します。"
  1151.                              "よろしいですか?", "消去") != 0)
  1152.             return;
  1153.         int i;
  1154.         for (i=0; i<CP_NUM; i++)
  1155.         {
  1156.             CPOINT *pcp;
  1157.             CP_GETDATA(i, &pcp);
  1158.             cpoint_delete(pcp);
  1159.         }
  1160.         int cpnum;
  1161.         cpnum = CP_NUM;
  1162.         for (i=0; i<cpnum; i++)
  1163.         {
  1164.             list_top(plPoints);
  1165.             if (!list_isOut(plPoints))
  1166.                 list_deleteData(plPoints);
  1167.         }
  1168.         curPoint = 0;
  1169.         dispPoints();
  1170.         desktop_checkActivity();
  1171.     }
  1172.  
  1173. /*--------------------------------------------------------*/
  1174. /*                   部品の呼び出し関数                   */
  1175. /*--------------------------------------------------------*/
  1176.  
  1177.     /*    initDataZPOINTS:idPointsWin:MJ_WINDOWL40の呼び出し関数    */
  1178.     int    PointsWinFunc(kobj, messId, argc, pev, trigger)
  1179.     int        kobj ;
  1180.     int        messId ;
  1181.     int        argc ;
  1182.     EVENT    *pev ;
  1183.     int        trigger ;
  1184.     {
  1185.         if (messId == MM_SHOW)
  1186.         {
  1187.             dispImages();
  1188.         }
  1189.         else if (messId == MM_MOVE)
  1190.         {
  1191.             RM_roundFramePosition(kobj,2,2);
  1192.             dispImages();
  1193.         }
  1194.         else if (messId == MM_MOUSEON && (pev->shift & SLEFTBTN)!=0)
  1195.         {
  1196.             POINT pt;
  1197.             pt = *(POINT*)&pev->info;
  1198.             int ret,rx,ry;
  1199.             if ((ret = checkOnImage(pt.x, pt.y, &rx,&ry)) >= 0)
  1200.             {
  1201.                 int pn;
  1202.                 int dx,dy;
  1203.                 if ((pn = checkOnPoint(ret,rx,ry,&dx,&dy)) >= 0)
  1204.                 {
  1205.                     if (pointCommand == 0 || pointCommand == 1)
  1206.                         moveControlPoint(ret,pn,dx,dy);
  1207.                     else if (pointCommand == 2)
  1208.                         deleteControlPoint(ret,pn);
  1209.                 }
  1210.                 else
  1211.                 {
  1212.                     if (pointCommand == 0)
  1213.                         points_makeNewPoints(pev);
  1214.                 }
  1215.             }
  1216.         #if 0
  1217.             else
  1218.             {
  1219.               /* 一時的にユーザー領域をなくす */
  1220.                 FRAME frUser, frResize;
  1221.                 MMI_SendMessage(kobj, MM_GETUSER, 2, &frUser, &frResize);
  1222.                 static FRAME frUserTemp = {0,0,0,0};
  1223.                 MMI_SendMessage(kobj, MM_SETUSER, 2, &frUserTemp, &frResize);
  1224.               /* 一時的にクリップ/ビシブル領域、原点をリセットする */
  1225.                 RM_setClipVisibleAllScr();
  1226.                 RM_setOriginZero();
  1227.               /* ユーザー領域がないものとして MM_MOUSEON (つまり移動) */
  1228.                 MMI_SendMessage(kobj, MM_MOUSEON, argc,pev,trigger);
  1229.               /* 原点、クリップ/ビジブル領域、ユーザー領域を復帰する */
  1230.                 RM_recoverOrigin();
  1231.                 RM_recoverClipVisible();
  1232.                 MMI_SendMessage(kobj, MM_SETUSER, 2, &frUser, &frResize);
  1233.             }
  1234.         #endif
  1235.         }
  1236.         else if (messId == MM_MOUSEON && (pev->shift & SRIGHTBTN)!=0)
  1237.         {
  1238.             if (pointType == CPOINT_LINE && nFromPoint >= 0)
  1239.                 nFromPoint = -1;
  1240.         }
  1241.         desktop_checkActivity();
  1242.         return NOERR ;
  1243.     }
  1244.  
  1245.     /*    initDataZPOINTS:idPointsTypeTIcon[0]:MJ_TICONL40の呼び出し関数    */
  1246.     /*    initDataZPOINTS:idPointsTypeTIcon[1]:MJ_TICONL40の呼び出し関数    */
  1247.     /*    initDataZPOINTS:idPointsTypeTIcon[2]:MJ_TICONL40の呼び出し関数    */
  1248.     int    PointsTypeTIconFunc(kobj, messId, argc, pev, trigger)
  1249.     int        kobj ;
  1250.     int        messId ;
  1251.     int        argc ;
  1252.     EVENT    *pev ;
  1253.     int        trigger ;
  1254.     {
  1255.         RM_pushRadioButton(kobj, idPointsWin, idPointsTypeTIcon,
  1256.                            INTNUM(idPointsTypeTIcon), &pointType);
  1257.         desktop_checkActivity();
  1258.         return NOERR ;
  1259.     }
  1260.  
  1261.     /*    initDataZPOINTS:idPointsCommandTIcon[0]:MJ_TICONL40の呼び出し関数    */
  1262.     /*    initDataZPOINTS:idPointsCommandTIcon[1]:MJ_TICONL40の呼び出し関数    */
  1263.     /*    initDataZPOINTS:idPointsCommandTIcon[2]:MJ_TICONL40の呼び出し関数    */
  1264.     int    PointsCommandTIconFunc(kobj, messId, argc, pev, trigger)
  1265.     int        kobj ;
  1266.     int        messId ;
  1267.     int        argc ;
  1268.     EVENT    *pev ;
  1269.     int        trigger ;
  1270.     {
  1271.         RM_pushRadioButton(kobj, idPointsWin, idPointsCommandTIcon,
  1272.                            INTNUM(idPointsCommandTIcon), &pointCommand);
  1273.         desktop_checkActivity();
  1274.         return NOERR ;
  1275.     }
  1276.  
  1277.     /*    initDataZPOINTS:idPointsEditDBtn[0]:MJ_DBUTTONL40の呼び出し関数    */
  1278.     /*    initDataZPOINTS:idPointsEditDBtn[1]:MJ_DBUTTONL40の呼び出し関数    */
  1279.     /*    initDataZPOINTS:idPointsEditDBtn[2]:MJ_DBUTTONL40の呼び出し関数    */
  1280.     /*    initDataZPOINTS:idPointsEditDBtn[3]:MJ_DBUTTONL40の呼び出し関数    */
  1281.     /*    initDataZPOINTS:idPointsEditDBtn[4]:MJ_DBUTTONL40の呼び出し関数    */
  1282.     /*    initDataZPOINTS:idPointsEditDBtn[5]:MJ_DBUTTONL40の呼び出し関数    */
  1283.     int    PointsEditDBtnFunc(kobj, messId, argc, pev, trigger)
  1284.     int        kobj ;
  1285.     int        messId ;
  1286.     int        argc ;
  1287.     EVENT    *pev ;
  1288.     int        trigger ;
  1289.     {
  1290.         int i;
  1291.         for (i=0; i<6; i++)
  1292.             if (kobj == idPointsEditDBtn[i])
  1293.                 break;
  1294.         int side;
  1295.         side = (i < 3 ? 0 : 1);
  1296.         if (kobj == idPointsEditDBtn[3*side+0] ||
  1297.             kobj == idPointsEditDBtn[3*side+1])
  1298.         {
  1299.             if (piOriginal[side] != NULL)
  1300.             {
  1301.                 IMAGE *pi;
  1302.                 if ((pi = image_copy(piOriginal[side])) != NULL)
  1303.                 {
  1304.                     if (kobj == idPointsEditDBtn[3*side+0])
  1305.                     {
  1306.                         image_delete(piOriginal[side]);
  1307.                         piOriginal[side] = NULL;
  1308.                         dispImages();
  1309.                     }
  1310.                     if (piPaste != NULL)
  1311.                         image_delete(piPaste);
  1312.                     piPaste = pi;
  1313.                 }
  1314.                 else
  1315.                     alert_noMemory("倉庫内の画像をカット/コピー");
  1316.             }
  1317.         }
  1318.         else if (kobj == idPointsEditDBtn[3*side+2])
  1319.         {
  1320.             if (piPaste != NULL)
  1321.             {
  1322.                 IMAGE *pi;
  1323.                 if ((pi = image_copy(piPaste)) != NULL)
  1324.                     points_storeImage(side,pi);
  1325.                 else
  1326.                     alert_noMemory("画像を倉庫へペースト");
  1327.             }
  1328.         }
  1329.         desktop_checkActivity();
  1330.         return NOERR ;
  1331.     }
  1332.  
  1333.     /*    initDataZPOINTS:idPointsDarkTIcon[0]:MJ_TICONL40の呼び出し関数    */
  1334.     /*    initDataZPOINTS:idPointsDarkTIcon[1]:MJ_TICONL40の呼び出し関数    */
  1335.     int    PointsDarkTIconFunc(kobj, messId, argc, pev, trigger)
  1336.     int        kobj ;
  1337.     int        messId ;
  1338.     int        argc ;
  1339.     EVENT    *pev ;
  1340.     int        trigger ;
  1341.     {
  1342.         
  1343.     
  1344.         desktop_checkActivity();
  1345.         return NOERR ;
  1346.     }
  1347.